#include "stdafx.h"
#include "ckRasterGLCM.h"

#include <fstream>

namespace ck
{
	namespace algorithm
	{
		namespace raster
		{
			RasterGLCM::RasterGLCM()
			{
			}

			RasterGLCM::RasterGLCM(z_uint32 greys)
			{
				m_greys = greys;
				m_stride = 1;
				m_width = m_greys;
				m_height = m_greys;

				m_data = new double[greys*greys];
				memset(m_data, 0, greys*greys * sizeof(double));
			}

			RasterGLCM::RasterGLCM(z_uint32 greys, z_uint32 stride)
			{
				m_greys = greys;
				m_stride = stride;
				m_width = m_greys;
				m_height = m_greys;

				m_data = new double[greys*greys];
				memset(m_data, 0, greys*greys * sizeof(double));
			}


			RasterGLCM::~RasterGLCM()
			{
			}

			z_uint32 RasterGLCM::GetGreys()
			{
				return m_greys;
			}

			z_uint32 RasterGLCM::GetStride()
			{
				return m_stride;
			}

			double RasterGLCM::ComputeAngularSecondMoment()
			{
				double asmv = 0.0f;

				double* ptr = m_data;
				for (z_int32 i = 0; i < m_greys; i++)
				{
					for (z_int32 j = 0; j < m_greys; j++, ptr++)
					{
						asmv += pow((*ptr), 2);
					}
				}
				return asmv;
			}

			double RasterGLCM::ComputeEntropy()
			{
				double entropy = 0.0f;

				double* ptr = m_data;
				for (z_int32 i = 0; i < m_greys; i++)
				{
					for (z_int32 j = 0; j < m_greys; j++, ptr++)
					{
						if ((*ptr) > 0)
						{
							entropy -= (*ptr) * log2((*ptr));
						}
					}
				}
				return entropy;
			}

			double RasterGLCM::ComputeConstrast()
			{
				double constrast = 0.0f;
				double v = 0.0;

				double* ptr = m_data;
				for (z_int32 i = 0; i < m_greys; i++)
				{
					for (z_int32 j = 0; j < m_greys; j++, ptr++)
					{
						if (*ptr != 0)
						{
							v = pow(i - j, 2) * (*ptr);
							constrast += v;
						}
					}
				}
				return constrast;
			}

			double RasterGLCM::ComputeCoorelation()
			{
				double sum = 0;
				double* ptr = m_data;
				double ux = 0.0, uy = 0.0, dx = 0.0, dy = 0.0;
				double c = 0.0;

				for (z_int32 i = 0; i < m_greys; i++)
				{
					for (z_int32 j = 0; j < m_greys; j++, ptr++)
					{
						sum += (i * j * (*ptr));

						ux += i * (*ptr);
						uy += j * (*ptr);
					}
				}

				ptr = m_data;
				for (z_int32 i = 0; i < m_greys; i++)
				{
					for (z_int32 j = 0; j < m_greys; j++, ptr++)
					{
						dx += pow((i - ux), 2.0) * (*ptr);
						dy += pow((j - uy), 2.0) * (*ptr);

						c += i * j * (*ptr);
					}
				}
				dx = sqrt(dx);
				dy = sqrt(dy);
				c = (sum - ux * uy) / (dx * dy);


				return c;
			}

			void RasterGLCM::Write(const char* szPath)
			{
				std::ofstream os(szPath);
				int v = 0;
				double* ptr = m_data;
				for (int i = 0; i < m_greys; i++)
				{
					for (int j = 0; j < m_greys; j++, ptr++)
					{
						v = *ptr;
						os << v << ",";
					}
					os << std::endl;
				}

				os.close();
			}
		}
	}
}